package de.in.michael.unnamed;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

import de.in.michael.unnamed.gfx.Art;
import de.in.michael.unnamed.gfx.Bitmap;
import de.in.michael.unnamed.screen.Screen;
import de.in.michael.unnamed.screen.TitleScreen;

public class GameComponent extends Canvas implements Runnable
{
	private static final long serialVersionUID = 1L;

	public static final String NAME = "unnamed";
	public static final String VERSION = "0.1b";
	public static final int WIDTH = 160;
	public static final int HEIGHT = 120;
	public static final int SCALE = 4;

	private boolean keepRunning = false;
	private BufferedImage screenImage;
	private Bitmap screenBitmap;
	private InputHandler inputHandler;
	private Screen screen;

	public GameComponent()
	{
		Dimension size = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);

		setMinimumSize(size);
		setMaximumSize(size);
		setPreferredSize(size);
	}

	public void start()
	{
		keepRunning = true;
		new Thread(this, "Game Thread").start();
	}

	public void init()
	{
		Art.init();

		screenImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		screenBitmap = new Bitmap(screenImage);
		inputHandler = new InputHandler(this);

		setScreen(new TitleScreen());
	}

	public void setScreen(Screen newScreen)
	{
		if (screen != null) screen.remove();

		screen = newScreen;

		if (screen != null) screen.init(this);
	}

	public void run()
	{
		init();

		long lastTime = System.nanoTime();
		double unprocessed = 0;
		double nsPerTick = 1000000000.0 / 60.0;
		int ticks = 0;
		int frames = 0;
		long lastTimer1 = System.currentTimeMillis();

		while (keepRunning)
		{
			long now = System.nanoTime();

			unprocessed += (now - lastTime) / nsPerTick;
			lastTime = now;

			while (unprocessed >= 1)
			{
				tick();
				ticks++;
				unprocessed -= 1;
			}

			render(screenBitmap);
			frames++;

			if (System.currentTimeMillis() - lastTimer1 > 1000)
			{
				lastTimer1 += 1000;
				System.out.println(ticks + " ticks, " + frames + " fps");
				ticks = 0;
				frames = 0;
			}

			swap();
		}
	}

	public void tick()
	{
		inputHandler.tick();
		screen.tick(inputHandler);
	}

	public void render(Bitmap b)
	{
		for (int i = 0; i < b.pixels.length; i++)
		{
			b.pixels[i] = 0;
		}

		screen.render(b);
	}

	public void swap()
	{
		BufferStrategy bs = getBufferStrategy();

		if (bs == null)
		{
			createBufferStrategy(3);
			return;
		}

		Graphics g = bs.getDrawGraphics();

		g.fillRect(0, 0, getWidth(), getHeight());
		g.drawImage(screenImage, (getWidth() - WIDTH * SCALE) / 2, (getHeight() - HEIGHT * SCALE) / 2, WIDTH * SCALE, HEIGHT * SCALE, null);
		g.dispose();
		bs.show();
	}

	public static void main(String[] args)
	{
		GameComponent gameComponent = new GameComponent();
		JFrame frame = new JFrame();

		frame.setTitle(NAME);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(new BorderLayout());
		frame.add(gameComponent, BorderLayout.CENTER);
		frame.pack();
		frame.setResizable(false);
		frame.setLocationRelativeTo(null);

		frame.setIconImage(Toolkit.getDefaultToolkit().getImage("res/icon.png"));

		frame.setVisible(true);

		gameComponent.start();
	}
}
